﻿using Microsoft.ServiceBus.Messaging;
using Newtonsoft.Json;
using Sustainalytics.DataLayer;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities;
using Sustainalytics.Insights.Service;
using Sustainalytics.Replication.Publisher;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Sustainalytics.Replication.Service
{
    static class MessageHandler
    {
        public static void ProcessMessage<T>(BrokeredMessage message, IRepositoryCollection<T> repository) where T : IEntity
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.Delete)
            {
                Guid guid = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());                
                repository.Delete(guid);                
            }
            else
            {
                var deserializedObject = JsonConvert.DeserializeObject<T>(message.GetBody<string>());

                if (operation == ReplicationUtils.Operation.Create)
                {
                    repository.Create(deserializedObject);
                }
                else if (operation == ReplicationUtils.Operation.Update)
                {
                    repository.Update(deserializedObject.Id, deserializedObject);
                }
                else if (operation == ReplicationUtils.Operation.CreateOrUpdate)
                {
                    repository.CreateOrUpdate(deserializedObject);
                }                
            }
        }

        public static void ProcessAuthMessage(BrokeredMessage message, IAccountsRepository accountsRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.SavePasswordByUserId)
            {
                var deserializedObject = JsonConvert.DeserializeObject<Tuple<Guid, string, DateTime>>(message.GetBody<string>());
                accountsRepository.SavePasswordByUserId(deserializedObject.Item1, deserializedObject.Item2, deserializedObject.Item3);
            }
            else if (operation == ReplicationUtils.Operation.SavePasswordByUsername)
            {
                var deserializedObject = JsonConvert.DeserializeObject<Tuple<string, string, DateTime>>(message.GetBody<string>());
                accountsRepository.SavePasswordByUsername(deserializedObject.Item1, deserializedObject.Item2, deserializedObject.Item3);
            }
        }

        public static void ProcessFilterMessage(BrokeredMessage message, IFiltersRepository filterRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.Update || operation == ReplicationUtils.Operation.Create)
            {
                var deserializedObject = JsonConvert.DeserializeObject<Entities.Filter>(message.GetBody<string>());
                filterRepository.SaveFilter(deserializedObject);                
            }            
            else if (operation == ReplicationUtils.Operation.Delete)
            {
                Guid guid = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());
                filterRepository.DeleteFilter(guid);
            }
        }

        public static void ProcessFilterCriteriaMessage(BrokeredMessage message, IFilterCriteriaRepository filterCriteriaRepoitory, ICompanyScreeningRepository companyScreeningRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.AddFilterCriteria)
            {
                var deserializedObject = JsonConvert.DeserializeObject<FilterCriteria>(message.GetBody<string>());
                companyScreeningRepository.AddFilterCriteria(deserializedObject);                    
            }
            if (operation == ReplicationUtils.Operation.UpdateFilterCriteria)
            {
                var deserializedObject = JsonConvert.DeserializeObject<FilterCriteria>(message.GetBody<string>());
                companyScreeningRepository.UpdateFilterCriteria(deserializedObject);
            }
            else if (operation == ReplicationUtils.Operation.DeleteResultOutput)
            {
                Guid guid = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());
                companyScreeningRepository.DeleteResultOutput(guid);
            }
            else if (operation == ReplicationUtils.Operation.DeleteFilterCriteria)
            {
                Guid guid = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());
                filterCriteriaRepoitory.DeleteFilterCriteria(guid);
            }
            else if (operation == ReplicationUtils.Operation.DeleteFilterCriteriaByIdTemplateIdAndFilterId)
            {
                var deserializedObject = JsonConvert.DeserializeObject<Tuple<Guid, Guid>>(message.GetBody<string>());
                filterCriteriaRepoitory.DeleteFilterCriteriaByIdTemplateIdAndFilterId(deserializedObject.Item1, deserializedObject.Item2);
            }
            else if (operation == ReplicationUtils.Operation.DeleteFilterCriteriaByFilterGroupId)
            { 
                var deserializedObject = JsonConvert.DeserializeObject<Tuple<Guid, Guid>>(message.GetBody<string>());
                filterCriteriaRepoitory.DeleteFilterCriteriaByFilterGroupId(deserializedObject.Item1, deserializedObject.Item2);
            }
            else if (operation == ReplicationUtils.Operation.DeleteAllFilterCriteriaByFilterId)
            {
                Guid guid = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());
                filterCriteriaRepoitory.DeleteAllFilterCriteriaByFilterId(guid);
            }
            else if (operation == ReplicationUtils.Operation.UpdateSelectedCriteriaOrderNumber)
            {
                var deserializedObject = JsonConvert.DeserializeObject<Tuple<Guid, List<Guid>>>(message.GetBody<string>());
                companyScreeningRepository.UpdateSelectedCriteriaOrderNumber(deserializedObject.Item1, deserializedObject.Item2);
            }
        }

        public static void ProcessMostRecentActivityMessage(BrokeredMessage message, IMostRecentActivityRepository mostRecentActivityRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.SaveMostRecentActivity)
            {
                var deserializedObject = JsonConvert.DeserializeObject<MostRecentActivity>(message.GetBody<string>());
                mostRecentActivityRepository.SaveMostRecentActivity(deserializedObject);
            }
        }

        public static void ProcessMostActiveReportMessage(BrokeredMessage message, IMostActiveReportRepository mostActiveReportRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.RecordReportActivity)
            {
                var deserializedObject = JsonConvert.DeserializeObject<MostActiveReport>(message.GetBody<string>());
                mostActiveReportRepository.RecordReportActivity(deserializedObject);
            }
        }

        public static void ProcesssPortfolioDetailsMessage(BrokeredMessage message, IRepositoryCollection<PortfolioDetails> portfolioDetailsRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.DeleteWhereByPortfolioId)
            {
                Guid portfolioId = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());
                portfolioDetailsRepository.DeleteWhere(p => p.PortfolioId == portfolioId);
            }
            else if (operation == ReplicationUtils.Operation.DeleteWhereBySecurityIdAndPortfolioId)
            {
                Tuple<Guid, Guid> deserializedObject = JsonConvert.DeserializeObject<Tuple<Guid, Guid>>(message.GetBody<string>());
                portfolioDetailsRepository.DeleteWhere(x => x.Id == deserializedObject.Item1 && x.PortfolioId == deserializedObject.Item2);
            }
            else if (operation == ReplicationUtils.Operation.CreateOrUpdateBatch)
            {
                List<PortfolioDetails> deserializedObject = JsonConvert.DeserializeObject<List<PortfolioDetails>>(message.GetBody<string>());
                portfolioDetailsRepository.CreateOrUpdateBatch(deserializedObject);
            }
        }

        public static void ProcesssPortfolioUserInputMessage(BrokeredMessage message, IRepositoryCollection<PortfolioUserInput> portfolioUserInputRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.DeleteWhereByPortfolioId)
            {
                Guid portfolioId = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());
                portfolioUserInputRepository.DeleteWhere(p => p.PortfolioId == portfolioId);
            }
            else if (operation == ReplicationUtils.Operation.DeleteWhereBySecurityIdAndPortfolioId)
            {
                Tuple<Guid, Guid> deserializedObject = JsonConvert.DeserializeObject<Tuple<Guid, Guid>>(message.GetBody<string>());
                portfolioUserInputRepository.DeleteWhere(x => x.Id == deserializedObject.Item1 && x.PortfolioId == deserializedObject.Item2);
            }
            else if (operation == ReplicationUtils.Operation.CreateOrUpdateBatch)
            {
                List<PortfolioUserInput> deserializedObject = JsonConvert.DeserializeObject<List<PortfolioUserInput>>(message.GetBody<string>());
                portfolioUserInputRepository.CreateOrUpdateBatch(deserializedObject);
            }
        }

        public static void ProcesssSubscribeToPortfolioMessage(BrokeredMessage message, ISubscribeToPortfolioRepository subscribeToPortfolioRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.Delete)
            {
                Guid subscribeId = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());
                subscribeToPortfolioRepository.Delete(subscribeId);
            }
            else if (operation == ReplicationUtils.Operation.UpdateStatus)
            {
                Tuple<Guid, bool> subscribeStatus = JsonConvert.DeserializeObject<Tuple<Guid, bool>>(message.GetBody<string>());
                subscribeToPortfolioRepository.UpdateStatus(subscribeStatus.Item1, subscribeStatus.Item2);
            }
            else
            {
                SubscribeToPortfolio subscribe = JsonConvert.DeserializeObject<SubscribeToPortfolio>(message.GetBody<string>());

                if (operation == ReplicationUtils.Operation.Insert)
                    subscribeToPortfolioRepository.Insert(subscribe);
                else if (operation == ReplicationUtils.Operation.Update)
                    subscribeToPortfolioRepository.Update(subscribe);
                else if (operation == ReplicationUtils.Operation.CreateOrUpdate)
                    subscribeToPortfolioRepository.CreateOrUpdate(subscribe);
            }
        }

        public static void ProcessInsightMessage(BrokeredMessage message, IInsightRepository insightRepository)
        {
            ReplicationUtils.Operation operation = ReplicationUtils.MessageOperation(message);

            if (operation == ReplicationUtils.Operation.Delete)
            {
                Guid insightId = JsonConvert.DeserializeObject<Guid>(message.GetBody<string>());
                insightRepository.Delete(insightId);
            }
            else if (operation == ReplicationUtils.Operation.DeleteBatch)
            {
                List<Guid> idsList = JsonConvert.DeserializeObject<List<Guid>>(message.GetBody<string>());
                insightRepository.Delete(idsList);
            }
            else if (operation == ReplicationUtils.Operation.UpdateBatch)
            {
                List<Tuple<Guid, InsightState>> insightList = JsonConvert.DeserializeObject<List<Tuple<Guid, InsightState>>>(message.GetBody<string>());
                insightRepository.Update(insightList);
            }
            else 
            {
                Insight insight = JsonConvert.DeserializeObject<Insight>(message.GetBody<string>());
                if (operation == ReplicationUtils.Operation.Create)
                    insightRepository.Create(insight);
                else if (operation == ReplicationUtils.Operation.Update)
                    insightRepository.Update(insight);
            }
        }
    }
}
